#ConfigNode.py

"""
 This is the base class for all the directive nodes. It contains the
 basic methods for adding, searching, reading and writing subnodes.
"""

from Cruft import Cruft
import Log

class ConfigNode:
    """
    This class is subclassed by the apache directives...

    children - list of children for this particular node.
    directive - the apache directive associated with this node
    args - the arguments for this directive
    comments - convenience variable to preserve the structure of the http.conf file by saving the comments
                that already exist in the file. Directives added through athabaskan should also be commented.
    parent - Who's your daddy?
    is_scoped - Is this a scoped node?                
    is_deleted - Has this node been deleted?
    file - The file this directive originated from
    """
    def __init__(self):
        self.directive = "Generic"
        self.args = [] 
        self.comment = ""
        self.children = []
        self.parent = None
        self.is_scoped = False
        self.is_deleted = False
        self.file = ""
        #The io methods and field are linked to an IO class by the setConfigIO method... 
        self.io = None
        self.read_config = None
        self.write_config = None
        Log.log_debug( "Created: " + self.directive )
        

    def __repr__(self):
        return self.directive + " " + ' '.join(self.args)

    def __str___(self):
        return self.directive + " " + ' '.join(self.args)
    
    def add_node(self, node):
        """Add a node to the tree"""
        curr_length = 0
        best_length = 0
        best_index = 0

        #Attempt to find the largest subsequence of like nodes 
        for i in range(0, len(self.children)):
            n = self.children[i]

            #Ignore Cruft nodes...
            if n.directive == "Cruft":
                continue

            if n.directive.lower() == node.directive.lower():
                curr_length += 1
            else:
                if curr_length > best_length:
                    best_length = curr_length
                    best_index = i - 1
                curr_length = 0

        self.insert_node(node, best_index)
        cruft = Cruft("\n")
        self.insert_node( cruft, best_index + 1)
    
    def insert_node(self, node, index):
        """Insert a node at the specified index"""
        node.parent = self
        if( not node.directive == "Cruft" ):
            if( not node.parent.io is None):
                node.setConfigIO( node.parent.io )
        self.children.insert(index, node)

    def append_node(self, node):
        """Append a node - skips the automatic formatting of add_node"""
        self.insert_node(node, -1)

    def get_node(self, directive):
        """
        Gets a specific child node... Doesn't recurse.
        """
        for n in self.children:
            if n.directive.lower() == directive.lower():
                return n
        return None

    def get_nodes(self, directive):
        """
        Get's a list of directive nodes
        """
        lst = []

        for n in self.children:
            if n.directive.lower() == directive.lower():
                lst.append(n)
        return lst

    def delete_node(self):
        """Marks this node as deleted"""
        self.is_deleted = True

    def search_tree(self, is_needle):
        """
        Do a depth first search of the tree using the given
        comparison function...
        """
        def _search(haystack):
            if haystack.children == []:
                return None
            
            for n in haystack.children:
                if is_needle(n):
                    return n
                #make sure we search across all child nodes...
                tmp = _search(n)
                if tmp is None:
                    continue
                else: return tmp
            #we really couldn't find anything...    
            return None
            
        return _search(self)

    def setConfigIO(self, configIO):
        """
        Set the IO routines... 
        """
        self.io = configIO
        self.read_config = configIO.read_config(self)
        self.write_config = configIO.write_config
       
## vim: ts=4 sw=4: 

